package top.codedance.iotp.manage.client.handler;

import com.alibaba.fastjson.JSONObject;
import top.codedance.iotp.common.constent.ClientType;
import top.codedance.iotp.common.constent.Command;
import top.codedance.iotp.common.entity.CommonEntity;
import top.codedance.iotp.common.handler.AbsractIdleHandler;
import top.codedance.iotp.common.util.AsymmetricEncryption;
import top.codedance.iotp.manage.Console;
import top.codedance.iotp.manage.client.Client;
import cd.io.netty.bootstrap.Bootstrap;
import cd.io.netty.channel.ChannelHandlerContext;
import cd.io.netty.channel.EventLoop;
import org.apache.log4j.Logger;

import java.nio.charset.StandardCharsets;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class IdleChannelHandler extends AbsractIdleHandler {

    private static Logger logger = Console.getLogger(IdleChannelHandler.class);

    private Client client;

    public IdleChannelHandler(Client client, Logger logger) {
        super(logger);
        this.client = client;
    }

    @Override
    protected void messageReceived(ChannelHandlerContext channelHandlerContext, CommonEntity commonEntity) throws Exception {
        if (commonEntity.getCommand() == Command.REGISTER_RECEIVE) {
            String bodyJson = new String(commonEntity.getBody(), StandardCharsets.UTF_8);
            JSONObject jsonObject = JSONObject.parseObject(bodyJson);
            String serverPublicKey = jsonObject.getString("serverPublicKey");
            Console.setServerPublicKey(serverPublicKey);
            String msg = jsonObject.getString("msg");
            logger.debug(msg);
        }
        super.messageReceived(channelHandlerContext, commonEntity);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable cause) throws Exception {
        logger.debug("---server " + channelHandlerContext.channel().remoteAddress().toString() + " diconnected---");
        channelHandlerContext.close();
    }

    @Override
    protected void handleAllIdle(ChannelHandlerContext channelHandlerContext) {
        sendPingMsg(channelHandlerContext);
        super.handleAllIdle(channelHandlerContext);
    }

    @Override
    public void channelInactive(ChannelHandlerContext channelHandlerContext) throws Exception {
        final EventLoop eventLoop = channelHandlerContext.channel().eventLoop();
        eventLoop.schedule(() -> {
            client.createBootstrap(new Bootstrap());
        }, 1L, TimeUnit.SECONDS);
        super.channelInactive(channelHandlerContext);
    }

    public void handlerAdded(ChannelHandlerContext channelHandlerContext) throws Exception {
        super.handlerAdded(channelHandlerContext);
    }

    public void handlerRemoved(ChannelHandlerContext channelHandlerContext) throws Exception {
        super.handlerRemoved(channelHandlerContext);
    }

    public void channelRegistered(ChannelHandlerContext channelHandlerContext) throws Exception {
        super.channelRegistered(channelHandlerContext);
    }

    public void channelUnregistered(ChannelHandlerContext channelHandlerContext) throws Exception {
        super.channelUnregistered(channelHandlerContext);
    }

    public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {
        CommonEntity commonEntity2 = new CommonEntity();
        commonEntity2.setCommand(Command.REGISTER);
        try {
            AsymmetricEncryption.KeyStringPair keyStringPair = AsymmetricEncryption.genKeyPair();
            Console.setKeyStringPair(keyStringPair);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("deviceId", UUID.randomUUID().toString());
            jsonObject.put("type", ClientType.CONSOLE.getId());
            jsonObject.put("publicKey", keyStringPair.getPublicKey());
            commonEntity2.setBody(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8));
            channelHandlerContext.write(commonEntity2.build());
            channelHandlerContext.flush();
            super.channelActive(channelHandlerContext);
        } catch (Exception ex) {
            logger.debug(ex.getMessage());
            channelHandlerContext.close();
        }
    }

    public void channelRead(ChannelHandlerContext channelHandlerContext, Object msg) throws Exception {
        super.channelRead(channelHandlerContext, msg);
    }

    public void channelReadComplete(ChannelHandlerContext channelHandlerContext) throws Exception {
        super.channelReadComplete(channelHandlerContext);
    }

    public void userEventTriggered(ChannelHandlerContext channelHandlerContext, Object evt) throws Exception {
        super.userEventTriggered(channelHandlerContext, evt);
    }

    public void channelWritabilityChanged(ChannelHandlerContext channelHandlerContext) throws Exception {
        super.channelWritabilityChanged(channelHandlerContext);
    }
}
